import mongodbInstance from '@/db/mongodb';
import { Collection, Document, Sort } from 'mongodb';

class BaseModel<T extends Document> {
  private tableName: string;

  private dbCollection: Collection | undefined;

  constructor(name: string) {
    this.tableName = name;
  }

  async init() {
    if (this.dbCollection) {
      return this.dbCollection;
    }
    const db = await mongodbInstance();
    if (!db) {
      throw new Error('数据库未连接');
    }
    const model = db.collection(this.tableName);
    this.dbCollection = model;
    return this.dbCollection;
  }

  /**
   * 插入数据
   * @param data 内容
   * @returns 结果
   */
  async insert(data: T) {
    const db = await this.init();
    return db.insertOne(data);
  }

  async insertMany(data: T[]) {
    const db = await this.init();
    return db.insertMany(data);
  }

  /**
   * 查询单条数据
   * @param data 查询条件
   * @returns 数据
   */
  async findOne(data: T) {
    const db = await this.init();
    const res = await db.findOne<T>(data, {});
    return res;
  }

  /**
   * 查询数量
   * @param query 查询条件
   * @returns 数量
   */
  async getCount(query: T) {
    const db = await this.init();
    return db.countDocuments(query);
  }

  /**
   * 查询列表
   * @param query 查询条件
   * @param sortFields 排序条件
   * @param pageIndex 当前页码
   * @param pageSize 每页数量
   * @returns 列表
   */
  async getList(query?: T, sortFields?: Sort, pageIndex = 1, pageSize = 20) {
    const db = await this.init();
    let ret = db.find(query || {});
    if (pageIndex && pageSize) {
      const page = pageIndex;
      const size = pageSize > 100 ? 100 : pageSize;
      if (sortFields) {
        ret = ret.sort(sortFields);
      }
      ret = ret.skip(size * (page - 1)).limit(size);
    }
    return ret.toArray();
  }

  /**
   * 更新数据
   * @param data 要更新的数据
   * @param query 筛选更新的条件
   * @returns 更新结果
   */
  async update(data: T, query: T) {
    const db = await this.init();
    return db.updateOne(query, {
      $set: data,
    });
  }

  /**
   * 删除集合
   */
  async deleteDrop() {
    const db = await this.init();
    return db.drop();
  }

  /**
   * 删除一条记录
   */
  async deleteOne(data: T) {
    const db = await this.init();
    return db.deleteOne(data);
  }

  /**
   * 删除多条记录
   */
  async deleteMany(data: T) {
    const db = await this.init();
    return db.deleteMany(data);
  }
}

export default BaseModel;
